#include<iostream>
#include<vector>
#include<sys/types.h>
#include<unistd.h>
#include<assert.h>
#include<sys/wait.h>
#include<ctime>

using std::cout;
using std::endl;
namespace proc
{
    class procTask
    {
    public:
        typedef void (procTask::* pfun)(void);

        void task_load(void)
        {
            task_list.push_back(&procTask::DownLoad);
            task_list.push_back(&procTask::UpLoad);
            task_list.push_back(&procTask::IOTask);
            task_list.push_back(&procTask::FlushTask);//这里需要加&是因为避免与调用成员函数冲突。
        }

        void DownLoad(void)
        {
            cout << "正在进行下载任务！" << endl;
            sleep(1);
            cout << "下载成功！" << endl;
        }

        void UpLoad(void)
        {
            cout << "正在长传！" << endl;
            sleep(1);
            cout << "上传成功！" << endl;
        }

        void IOTask(void)
        {
            cout << "IO任务！" << endl;
            sleep(1);
            cout << "IO任务成功！" << endl;
        }

        void FlushTask(void)
        {
            cout << "正在刷新！" << endl;
            sleep(1);
            cout << "刷新成功！" << endl;
        }
    public:
        std::vector<pfun> task_list;
    };

    class procpool
    {
    public:
        procpool(const int& proc_mun = 0)
            :proc_mun_(proc_mun)
        {
            //初始换
            pipe_write_.resize(proc_mun_);
            proc_id_.resize(proc_mun);
            std::vector<int> del_fd;

            for (int i = 0; i < proc_mun; i++)
            {
                //创建管道
                int pipe_fd[2];
                int n = pipe(pipe_fd);
                assert(n != -1);
                pipe_write_[i] = pipe_fd[1];

                //创建子进程
                int id = fork();
                assert(id != -1);
                proc_id_[i] = id;
                if (id == 0)
                {
                    //删除继承成的写通道
                    for (int n = 0; n < del_fd.size(); n++)
                        close(del_fd[n]);
                    while(true)
                    {
                        int buff = -1;
                        int s = read(pipe_fd[0], &buff, sizeof(int));
                        assert(s != -1);
                        if (s == 0)
                            break;
                        if (s != 0 && buff > 0 || buff < 4)
                        {
                            //获取任务
                            procTask task;
                            task.task_load();
                            //执行任务
                            (task.*task.task_list[buff])();
                        }
                    }
                     exit(0);
                }
                close(pipe_fd[0]);//关闭父进程的读通道
                del_fd.push_back(pipe_fd[1]);//记录写通道
            }
        }

        //返回写管道
        std::vector<int> Get_PipeWrite(void)
        {
            return pipe_write_;
        }

        //返回子进程id
        std::vector<int> Get_ProcId(void)
        {
            return proc_id_;
        }

    private:
        int proc_mun_;//子进程数量
        std::vector<int> pipe_write_;//存放写管道
        std::vector<int> proc_id_;//存放子进程id
    };
}

using namespace proc;

int main()
{ 
    //创建任务列表
    proc::procTask task_list;
    task_list.task_load();

    //设定随机数种子
    srand(time(0));

    //分配任务
    proc::procpool task_procpool(6);
    bool quit = 0;
    while(!quit)
    {
        int proc_index = rand() % 6;
        int task_index = rand() % 4;
        write((task_procpool.Get_PipeWrite())[proc_index], &task_index, sizeof(int));
        sleep(2);
    }

    //删除子进程
    for (int i = 0; i < task_procpool.Get_PipeWrite().size(); i++)
        close(task_procpool.Get_PipeWrite()[i]);

    return 0;
}